﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;

namespace LabMonitorRemote
{
    public abstract class DewkCommand
    {
        protected const Int32 _Port = 10001;

        //Statics
        static Int32 waitPreClear = 100;
        static Int32 waitPostRead = 5;
        static Int32 waitRead = 1000;
        static Int32 waitPostWrite = 5; // See about dropping to 20ms
        static Int32 writeTimeout = 10;
        static Int32 readTimeout = 100;

        //Logger Specific variables
        String commandToSend;
        IPEndPoint IPAddress;
        TcpClient client;
        NetworkStream netStream;

        public IPEndPoint IpEndPoint
        {
            get { return IPAddress; }
            private set { IPAddress = value; }
        }
        
        public DewkCommand(IPEndPoint ipEndPoint)
        {
            IPAddress = ipEndPoint;
            ConnectClient();
        }

        public string CommandToSend
        {
            get { return commandToSend; }
            set { commandToSend = value; }
        }

        public TcpClient TCPClient
        {
            get { return this.client; }
        }

        public NetworkStream NetStream
        {
            get { return this.netStream; }
        }


        void ConnectClient()
        {
            // Create this LoggerDownload TcpClient object
            client = new TcpClient();
            client.NoDelay = true;
            client.Client.NoDelay = true;
            //client.Client.Blocking = true;
            //client.SendBufferSize = 256;
            //client.ReceiveBufferSize = 512;
            client.ExclusiveAddressUse = false;

            try
            {
                client.Connect(this.IPAddress);
            }
            catch (Exception e)
            {
                Console.WriteLine("     Error connecting to client:");
                Console.WriteLine(e.ToString());
            }
            
            // Create this LoggerDownload NetworkStream object            

            try
            {
                netStream = client.GetStream();

                // Set netStream properties
                netStream.WriteTimeout = writeTimeout;
                netStream.ReadTimeout = readTimeout;
            }
            catch (InvalidOperationException e)
            {
                Console.WriteLine("     The TCPClient is not connected to a remote host...");
                Console.WriteLine(e.ToString());
            }               


        }

        public void ManuallyCloseClient()
        {
            try
            {
                client.Client.Shutdown(SocketShutdown.Send);
            }
            catch (System.Net.Sockets.SocketException e)
            {
                string errorMessage = string.Format("Cannot send data to {0} because the socket is not connected.",this.IpEndPoint.Address.ToString());
                Console.WriteLine();
            }
            finally
            {
                if (netStream != null)
                {// Close netStream if instanced. 
                    netStream.Close();
                }
                client.Close();
            }
        }

        public event CommandSentEventHandler CommandSent;
        public delegate void CommandSentEventHandler(DewkCommand dc, EventArgs e);
        private void OnCommandSent()
        {
            if (CommandSent != null)
            {
                CommandSent(this, new EventArgs());
            }
        }


        public async void WriteCommand()
        {
            Byte[] bCmd = System.Text.Encoding.ASCII.GetBytes(commandToSend + " ");
            Int32 writeBufferSize = bCmd.Length;
            bCmd[writeBufferSize - 1] = 13;
            client.SendBufferSize = writeBufferSize; // Set buffer size to exact command size

            // ERROR  - will error here if there is no ip to connect to.
            try
            {
                var writeResult = netStream.WriteAsync(bCmd, 0, bCmd.Length);
                Console.WriteLine("Writing command to stream: {0}", commandToSend);
                var flushResult = netStream.FlushAsync();
                await flushResult;
                OnCommandSent();
            }
            catch (System.NullReferenceException nre)
            {
                string errorMessage = 
                    string.Format("Error sending network packets to the specified target {0} - Please check your connections.",this.IpEndPoint.Address.ToString()); 
                Console.WriteLine(errorMessage);
            }
            // Await writing command to stream
            //await writeResult;

            // Flush netStream
            

            /*
            for (int i = 0; i < 3; i++)
            {
                Console.WriteLine("     Currently Awaiting Flush...");
            }
             */ 
 //fire event

            /*
            for (int i = 0; i < 3; i++)
            {
                Console.WriteLine("     Flush complete!");
            }
            */
              
            if (waitPostWrite > 0)
                Thread.Sleep(waitPostWrite);
        }    
    } // CLASS DewkCommand

    public class OpenDateRangeDewkCommand : DewkCommand
    {
        DateTime downloadFromDate;
        DateTime downloadToDate;
        String openCommand;

        public OpenDateRangeDewkCommand(IPEndPoint ipEndPoint, DateTime fromDate, DateTime toDate)
            : base(ipEndPoint)
        {
            downloadFromDate = fromDate;
            downloadToDate = toDate;
            openCommand = BuildOpenCmd(fromDate, toDate);
            base.CommandToSend = openCommand;
        }

        private string BuildOpenCmd(DateTime fromDate, DateTime toDate)
        {// Open from beginning of fromDate to 
            String openCmd = "DAT:REC:OPEN ";
            openCmd += fromDate.Year.ToString() + ",";
            openCmd += fromDate.Month.ToString() + ",";
            openCmd += fromDate.Day.ToString() + ",0,0,0, ";
            openCmd += toDate.Year.ToString() + ",";
            openCmd += toDate.Month.ToString() + ",";
            openCmd += toDate.Day.ToString() + ",23,59,59,";
            return openCmd;
        }

    } // CLASS OpenDateRangeDewkCommand

    public class RequestDatasetSizeDewkCommand : DewkCommand
    {
        public RequestDatasetSizeDewkCommand(IPEndPoint ipEndPoint)
            : base(ipEndPoint)
        {
            base.CommandToSend = "DAT:REC:OPEN?";
        }
    } // CLASS GetDatasetSizeDewkCommand

    public class RequestDataBlockDewkCommand : DewkCommand
    {
        String readCommand = "DAT:REC:READ?";
        
        public RequestDataBlockDewkCommand(IPEndPoint ipEndPoint, Int32 DataBlockSize = 256)
            : base(ipEndPoint)
        {
            base.CommandToSend = readCommand + " " + DataBlockSize.ToString();
        }

    } // CLASS RequestDataBlockDewkCommand

    public class RequestDataBlockResendDewkCommand : DewkCommand
    {
        String resendCommand = "DAT:REC:RES?";

        public RequestDataBlockResendDewkCommand(IPEndPoint ipEndPoint)
            : base(ipEndPoint)
        {
            base.CommandToSend = resendCommand;
        }

    } // CLASS RequestDataBlockResendDewkCommand

    public class IDNDewkCommand : DewkCommand
    {
        //const Int32 _Port = 10001;
        string _IdnCommand = "*IDN?";
        
        public IDNDewkCommand(string IpAddress)
            : base(new IPEndPoint(IPAddress.Parse(IpAddress),_Port))
        {
            base.CommandToSend = _IdnCommand;
        }

        public IDNDewkCommand(IPEndPoint ipEndPoint)
            : base(ipEndPoint)
        {
            base.CommandToSend = _IdnCommand;
        }
    } // CLASS IDNDewkCommand

    public class GetMeasurmentDewkCommand : DewkCommand
    {
        string _GetMeasCommand = "READ?";

        public GetMeasurmentDewkCommand(string IpAddress)
            : base(new IPEndPoint(IPAddress.Parse(IpAddress), _Port))
        {
            base.CommandToSend = _GetMeasCommand;
        }

        public GetMeasurmentDewkCommand(IPEndPoint IpEndPoint)
            : base(IpEndPoint)
        {
            base.CommandToSend = _GetMeasCommand;
        }
    } // GetMeasurmentDewkCommand

    public class GetHumidityRecordingState : DewkCommand
    {
        string _GetHumidityRecordingStateCommand = "RDAT:REC:FEED:RHUM"; //DAT:REC:FEED:RHUM<chn>?

        public GetHumidityRecordingState(string IpAddress, Int32 Channel)
            : base(new IPEndPoint(IPAddress.Parse(IpAddress), _Port))
        {
            SetCommand(Channel);
        }

        public GetHumidityRecordingState(IPEndPoint IpAddress, Int32 Channel)
            : base(IpAddress)
        {
            SetCommand(Channel);
        }

        private void SetCommand(Int32 Channel)
        {
            base.CommandToSend = _GetHumidityRecordingStateCommand + Channel.ToString() + "?";
        }
    } //GetHumidityRecordingState
    
    public class SetHumidityRecordingState : DewkCommand
    {
        string _SetHumidityRecordingStateCommand = "DAT:REC:FEED:RHUM"; // DAT:REC:FEED:RHUM<chn><bool>

        public SetHumidityRecordingState(string IpAddress, Int32 Channel, Boolean Enabled)
            : base(new IPEndPoint(IPAddress.Parse(IpAddress), _Port))
        {
            if (ChannelNumberCheck(Channel))
            {
                 SetCommand(Channel, Enabled); ;
            }
        }
            
        public SetHumidityRecordingState(IPEndPoint IpAddress, Int32 Channel, Boolean Enabled)
            : base(IpAddress)
        {
            if (ChannelNumberCheck(Channel))
            {
                SetCommand(Channel, Enabled);
            }
        }

        private void SetCommand(Int32 Channel, Boolean Enabled)
        {
            base.CommandToSend = string.Format("{0}{1} {2}",_SetHumidityRecordingStateCommand,
                        Channel.ToString(), EnableDisable(Enabled));
        }

        private string EnableDisable(Boolean state)
        {
            if (state)
                return "1";
            else
                return "0";
        }

        private Boolean ChannelNumberCheck(Int32 channel)
        {
            if (channel < 1 || channel > 2)
            {
                Console.WriteLine("Error caught in method ChannelNumberCheck: channel number must be either 1 or 2");
                return false;
            }
            else
                return true;
        }
    } // SetHumidityRecordingState

    public class GetTemperatureRecordingState : DewkCommand
    {
        string _GetHumidityRecordingStateCommand = "DAT:REC:FEED:TEMP"; //DAT:REC:FEED:RHUM<chn>?

        public GetTemperatureRecordingState(string IpAddress, Int32 Channel)
            : base(new IPEndPoint(IPAddress.Parse(IpAddress), _Port))
        {
            SetCommand(Channel);
        }

        public GetTemperatureRecordingState(IPEndPoint IpAddress, Int32 Channel)
            : base(IpAddress)
        {
            SetCommand(Channel);
        }

        private void SetCommand(Int32 Channel)
        {
            base.CommandToSend = _GetHumidityRecordingStateCommand + Channel.ToString() + "?";
        }
    } //GetTemperatureRecordingState
    
    public class SetTemperatureRecordingState : DewkCommand
    {
        string _SetHumidityRecordingStateCommand = "DAT:REC:FEED:TEMP"; // DAT:REC:FEED:RHUM<chn><bool>

        public SetTemperatureRecordingState(string IpAddress, Int32 Channel, Boolean Enabled)
            : base(new IPEndPoint(IPAddress.Parse(IpAddress), _Port))
        {
            if (ChannelNumberCheck(Channel))
            {
                base.CommandToSend = string.Format("{0}{1} {2}",_SetHumidityRecordingStateCommand,
                                        Channel.ToString(), EnableDisable(Enabled));
            }
        }

        public SetTemperatureRecordingState(IPEndPoint IpAddress, Int32 Channel, Boolean Enabled)
            : base(IpAddress)
        {
            if (ChannelNumberCheck(Channel))
            {
                base.CommandToSend = _SetHumidityRecordingStateCommand +
                                        Channel.ToString() + EnableDisable(Enabled);
            }
        }

        private string EnableDisable(Boolean state)
        {
            if (state)
                return "1";
            else
                return "0";
        }

        private Boolean ChannelNumberCheck(Int32 channel)
        {
            if (channel < 1 || channel > 2)
            {
                Console.WriteLine("Error caught in method ChannelNumberCheck: channel number must be either 1 or 2");
                return false;
            }
            else
                return true;
        }
    } // SetTemperatureRecordingState

    public class GetDataRecordingTimer : DewkCommand
    {
        string _GetDataRecordingTimerCommand = "DAT:REC:TIM?";

        public GetDataRecordingTimer(string IpAddress)
            : base(new IPEndPoint(IPAddress.Parse(IpAddress), _Port))
        {
            SetCommand();
        }

        public GetDataRecordingTimer(IPEndPoint IpAddress)
            : base(IpAddress)
        {
            SetCommand();
        }

        private void SetCommand()
        {
            base.CommandToSend = _GetDataRecordingTimerCommand;
        }
    } // GetDataRecordingTimer

    public class SetDataRecordingTimer : DewkCommand
    {
        private readonly List<Int32> _RecIntervals = new List<int>(){1,2,5,10,15,30,60,120,300,600,900,1200,1800,3600};
        string _GetDataRecordingTimerCommand = "DAT:REC:TIM ";

        public SetDataRecordingTimer(string IpAddress, Int32 RecTimer)
            : base(new IPEndPoint(IPAddress.Parse(IpAddress), _Port))
        {
            SetCommand(RecTimer);
        }

        public SetDataRecordingTimer(IPEndPoint IpAddress, Int32 RecTimer)
            : base(IpAddress)
        {
            SetCommand(RecTimer);
        }

        private void SetCommand(Int32 RecTimer)
        {
            if (_RecIntervals.IndexOf(RecTimer) != -1)
                base.CommandToSend = _GetDataRecordingTimerCommand + RecTimer.ToString();
            else
            {
                // use default timer of 300 seconds
                Console.WriteLine("Time interval specified is not valid. \nValid intervals are ");
                foreach (Int32 i in _RecIntervals)
                    Console.Write("{0}, ",i);
                Console.WriteLine("Setting recording interval to 300 seconds.");
                base.CommandToSend = _GetDataRecordingTimerCommand + "300";
            }
        }
    } // SetDataRecordingTimer

    public class GetTemperatureLowAlarmEnabled : DewkCommand
    {
        public GetTemperatureLowAlarmEnabled(string IpAddress, Int32 ChannelNumber)
            : base(new IPEndPoint(IPAddress.Parse(IpAddress), _Port))
        {
            SetCommand(ChannelNumber);
        }

        public GetTemperatureLowAlarmEnabled(IPEndPoint IpAddress, Int32 ChannelNumber)
            : base(IpAddress)
        {
            SetCommand(ChannelNumber);
        }

        private void SetCommand(Int32 ChannelNumber)
        {
            string command = string.Format("ALAR:TEMP{0}:LOW:ENAB?", ChannelNumber);
            base.CommandToSend = command;
        }
    }

    public class SetTemperatureLowAlarmEnabled : DewkCommand
    {
        public SetTemperatureLowAlarmEnabled(string IpAddress, Int32 ChannelNumber, Boolean Enabled)
            : base(new IPEndPoint(IPAddress.Parse(IpAddress), _Port))
        {
            SetCommand(ChannelNumber, Enabled);
        }

        public SetTemperatureLowAlarmEnabled(IPEndPoint IpAddress, Int32 ChannelNumber, Boolean Enabled)
            : base(IpAddress)
        {
            SetCommand(ChannelNumber, Enabled);
        }
        private void SetCommand(Int32 ChannelNumber,Boolean Enabled)
        {
            string command = string.Format("ALAR:TEMP{0}:LOW:ENAB {1}", ChannelNumber,EnableDisable(Enabled));
            base.CommandToSend = command;
        }
        private string EnableDisable(Boolean state)
        {
            if (state)
                return "1";
            else
                return "0";
        }
    }

    public class GetTemperatureHighAlarmEnabled : DewkCommand
    {
        public GetTemperatureHighAlarmEnabled(string IpAddress, Int32 ChannelNumber)
            : base(new IPEndPoint(IPAddress.Parse(IpAddress), _Port))
        {
            SetCommand(ChannelNumber);
        }

        public GetTemperatureHighAlarmEnabled(IPEndPoint IpAddress, Int32 ChannelNumber)
            : base(IpAddress)
        {
            SetCommand(ChannelNumber);
        }
        private void SetCommand(Int32 ChannelNumber)
        {
            string command = string.Format("ALAR:TEMP{0}:UPP:ENAB?", ChannelNumber);
            base.CommandToSend = command;
        }
    }

    public class SetTemperatureHighAlarmEnabled : DewkCommand
    {
        public SetTemperatureHighAlarmEnabled(string IpAddress, Int32 ChannelNumber, Boolean Enabled)
            : base(new IPEndPoint(IPAddress.Parse(IpAddress), _Port))
        {
            SetCommand(ChannelNumber, Enabled);
        }

        public SetTemperatureHighAlarmEnabled(IPEndPoint IpAddress, Int32 ChannelNumber, Boolean Enabled)
            : base(IpAddress)
        {
            SetCommand(ChannelNumber, Enabled);
        }
        private void SetCommand(Int32 ChannelNumber, Boolean Enabled)
        {
            string command = string.Format("ALAR:TEMP{0}:UPP:ENAB {1}", ChannelNumber, EnableDisable(Enabled));
            base.CommandToSend = command;
        }
        private string EnableDisable(Boolean state)
        {
            if (state)
                return "1";
            else
                return "0";
        }
    }

    public class GetHumidityLowAlarmEnabled : DewkCommand
    {
        public GetHumidityLowAlarmEnabled(string IpAddress, Int32 ChannelNumber)
            : base(new IPEndPoint(IPAddress.Parse(IpAddress), _Port))
        {
            SetCommand(ChannelNumber);
        }

        public GetHumidityLowAlarmEnabled(IPEndPoint IpAddress, Int32 ChannelNumber)
            : base(IpAddress)
        {
            SetCommand(ChannelNumber);
        }
        private void SetCommand(Int32 ChannelNumber)
        {
            string command = string.Format("ALAR:RHUM{0}:LOW:ENAB?", ChannelNumber);
            base.CommandToSend = command;
        }
    }

    public class SetHumidityLowAlarmEnabled : DewkCommand
    {
        public SetHumidityLowAlarmEnabled(string IpAddress, Int32 ChannelNumber, Boolean Enabled)
            : base(new IPEndPoint(IPAddress.Parse(IpAddress), _Port))
        {
            SetCommand(ChannelNumber, Enabled);
        }

        public SetHumidityLowAlarmEnabled(IPEndPoint IpAddress, Int32 ChannelNumber, Boolean Enabled)
            : base(IpAddress)
        {
            SetCommand(ChannelNumber, Enabled);
        }
        private void SetCommand(Int32 ChannelNumber, Boolean Enabled)
        {
            string command = string.Format("ALAR:RHUM{0}:LOW:ENAB {1}", ChannelNumber, EnableDisable(Enabled));
            base.CommandToSend = command;
        }
        private string EnableDisable(Boolean state)
        {
            if (state)
                return "1";
            else
                return "0";
        }
    }
    
    public class GetHumidityHighAlarmEnabled : DewkCommand
    {
        public GetHumidityHighAlarmEnabled(string IpAddress, Int32 ChannelNumber)
            : base(new IPEndPoint(IPAddress.Parse(IpAddress), _Port))
        {
            SetCommand(ChannelNumber);
        }

        public GetHumidityHighAlarmEnabled(IPEndPoint IpAddress, Int32 ChannelNumber)
            : base(IpAddress)
        {
            SetCommand(ChannelNumber);
        }
        private void SetCommand(Int32 ChannelNumber)
        {
            string command = string.Format("ALAR:RHUM{0}:UPP:ENAB?", ChannelNumber);
            base.CommandToSend = command;
        }
    }

    public class SetHumidityHighAlarmEnabled : DewkCommand
    {
        public SetHumidityHighAlarmEnabled(string IpAddress, Int32 ChannelNumber, Boolean Enabled)
            : base(new IPEndPoint(IPAddress.Parse(IpAddress), _Port))
        {
            SetCommand(ChannelNumber, Enabled);
        }

        public SetHumidityHighAlarmEnabled(IPEndPoint IpAddress, Int32 ChannelNumber, Boolean Enabled)
            : base(IpAddress)
        {
            SetCommand(ChannelNumber, Enabled);
        }
        private void SetCommand(Int32 ChannelNumber, Boolean Enabled)
        {
            string command = string.Format("ALAR:RHUM{0}:UPP:ENAB {1}", ChannelNumber, EnableDisable(Enabled));
            base.CommandToSend = command;
        }
        private string EnableDisable(Boolean state)
        {
            if (state)
                return "1";
            else
                return "0";
        }
    }

    public class GetUpperTemperatureLimit : DewkCommand
    {
        // Get Upper Temperature Alarm Limit on the specified channel.
        //"ALAR:TEMP:<chn>UPP:LIM?
        public GetUpperTemperatureLimit(string IpAddress, Int32 ChannelNumber)
            : base(new IPEndPoint(IPAddress.Parse(IpAddress), _Port))
        {
            SetCommand(ChannelNumber);
        }
        public GetUpperTemperatureLimit(IPEndPoint IpAddress, Int32 ChannelNumber)
            : base(IpAddress)
        {
            SetCommand(ChannelNumber);
        }
        private void SetCommand(Int32 ChannelNumber)
        {
            base.CommandToSend = string.Format("ALAR:TEMP{0}:UPP:LIM?", ChannelNumber);
        }
    } // GetUpperTemperatureLimit

    public class SetUpperTemperatureLimit : DewkCommand
    {
        //"ALAR:TEMP:<chn>UPP:LIM: <float>
        public SetUpperTemperatureLimit(string IpAddress, Int32 ChannelNumber, Double Limit)
            : base(new IPEndPoint(IPAddress.Parse(IpAddress), _Port))
        {
            SetCommand(ChannelNumber, Limit);
        }
        public SetUpperTemperatureLimit(IPEndPoint IpAddress, Int32 ChannelNumber, Double Limit)
            : base(IpAddress)
        {
            SetCommand(ChannelNumber, Limit);
        }
        private void SetCommand(Int32 ChannelNumber, Double Limit)
        {
            base.CommandToSend = string.Format("ALAR:TEMP{0}:UPP:LIM {1:N2}", ChannelNumber, Limit);
        }
    } // SetUpperTemperatureLimit

    public class GetLowerTemperatureLimit : DewkCommand
    {
        // Get Upper Temperature Alarm Limit on the specified channel.
        //"ALAR:TEMP:<chn>UPP:LIM?
        public GetLowerTemperatureLimit(string IpAddress, Int32 ChannelNumber)
            : base(new IPEndPoint(IPAddress.Parse(IpAddress), _Port))
        {
            SetCommand(ChannelNumber);
        }
        public GetLowerTemperatureLimit(IPEndPoint IpAddress, Int32 ChannelNumber)
            : base(IpAddress)
        {
            SetCommand(ChannelNumber);
        }
        private void SetCommand(Int32 ChannelNumber)
        {
            base.CommandToSend = string.Format("ALAR:TEMP{0}:LOW:LIM?", ChannelNumber);
        }
    } // GetLowerTemperatureLimit

    public class SetLowerTemperatureLimit : DewkCommand
    {
        //"ALAR:TEMP:<chn>UPP:LIM: <float>
        public SetLowerTemperatureLimit(string IpAddress, Int32 ChannelNumber, Double Limit)
            : base(new IPEndPoint(IPAddress.Parse(IpAddress), _Port))
        {
            SetCommand(ChannelNumber, Limit);
        }
        public SetLowerTemperatureLimit(IPEndPoint IpAddress, Int32 ChannelNumber, Double Limit)
            : base(IpAddress)
        {
            SetCommand(ChannelNumber, Limit);
        }
        private void SetCommand(Int32 ChannelNumber, Double Limit)
        {
            base.CommandToSend = string.Format("ALAR:TEMP{0}:LOW:LIM {1:N2}", ChannelNumber, Limit);
        }
    } // SetLowerTemperatureLimit

    public class GetUpperHumidityLimit : DewkCommand
    {
        // Get Upper Temperature Alarm Limit on the specified channel.
        //"ALAR:TEMP:<chn>UPP:LIM?
        public GetUpperHumidityLimit(string IpAddress, Int32 ChannelNumber)
            : base(new IPEndPoint(IPAddress.Parse(IpAddress), _Port))
        {
            SetCommand(ChannelNumber);
        }
        public GetUpperHumidityLimit(IPEndPoint IpAddress, Int32 ChannelNumber)
            : base(IpAddress)
        {
            SetCommand(ChannelNumber);
        }
        private void SetCommand(Int32 ChannelNumber)
        {
            base.CommandToSend = string.Format("ALAR:RHUM{0}:UPP:LIM?", ChannelNumber);
        }
    } // GetUpperHumidityLimit

    public class SetUpperHumidityLimit : DewkCommand
    {
        //"ALAR:TEMP:<chn>UPP:LIM: <float>
        public SetUpperHumidityLimit(string IpAddress, Int32 ChannelNumber, Double Limit)
            : base(new IPEndPoint(IPAddress.Parse(IpAddress), _Port))
        {
            SetCommand(ChannelNumber, Limit);
        }
        public SetUpperHumidityLimit(IPEndPoint IpAddress, Int32 ChannelNumber, Double Limit)
            : base(IpAddress)
        {
            SetCommand(ChannelNumber, Limit);
        }
        private void SetCommand(Int32 ChannelNumber, Double Limit)
        {
            base.CommandToSend = string.Format("ALAR:RHUM{0}:UPP:LIM {1:N2}", ChannelNumber, Limit);
        }
    } // SetUpperHumidityLimit

    public class GetLowerHumidityLimit : DewkCommand
    {
        // Get Upper Temperature Alarm Limit on the specified channel.
        //"ALAR:TEMP:<chn>UPP:LIM?
        public GetLowerHumidityLimit(string IpAddress, Int32 ChannelNumber)
            : base(new IPEndPoint(IPAddress.Parse(IpAddress), _Port))
        {
            SetCommand(ChannelNumber);
        }
        public GetLowerHumidityLimit(IPEndPoint IpAddress, Int32 ChannelNumber)
            : base(IpAddress)
        {
            SetCommand(ChannelNumber);
        }
        private void SetCommand(Int32 ChannelNumber)
        {
            base.CommandToSend = string.Format("ALAR:RHUM{0}:LOW:LIM?", ChannelNumber);
        }
    } // GetLowerHumidityLimit

    public class SetLowerHumidityLimit : DewkCommand
    {
        //"ALAR:TEMP:<chn>UPP:LIM: <float>
        public SetLowerHumidityLimit(string IpAddress, Int32 ChannelNumber, Double Limit)
            : base(new IPEndPoint(IPAddress.Parse(IpAddress), _Port))
        {
            SetCommand(ChannelNumber, Limit);
        }
        public SetLowerHumidityLimit(IPEndPoint IpAddress, Int32 ChannelNumber, Double Limit)
            : base(IpAddress)
        {
            SetCommand(ChannelNumber, Limit);
        }
        private void SetCommand(Int32 ChannelNumber, Double Limit)
        {
            base.CommandToSend = string.Format("ALAR:RHUM{0}:LOW:LIM {1:N2}", ChannelNumber, Limit);
        }
    } // SetLowerHumidityLimit

    public class GetChannelEnabled : DewkCommand
    {
        string _GetChannelEnabledCommand = "ROUT:OPEN?"; //ROUT:OPEN? <chn>?

        public GetChannelEnabled(string IpAddress, Int32 Channel)
            : base(new IPEndPoint(IPAddress.Parse(IpAddress), _Port))
        {
            SetCommand(Channel);
        }

        public GetChannelEnabled(IPEndPoint IpAddress, Int32 Channel)
            : base(IpAddress)
        {
            SetCommand(Channel);
        }

        private void SetCommand(Int32 Channel)
        {
            base.CommandToSend = _GetChannelEnabledCommand + Channel.ToString() + "?";
        }
    } // GetChannelEnabled

    public class SetChannelEnabled : DewkCommand
    {
        string _EnableChannelCommand = "ROUT:OPEN"; //ROUT:OPEN <chn>
        string _DisableChannelCommand = "ROUT:CLOS"; //ROUT:OPEN <chn>

        public SetChannelEnabled(string IpAddress, Int32 Channel, Boolean Enabled)
            : base(new IPEndPoint(IPAddress.Parse(IpAddress), _Port))
        {
            SetCommand(Channel, Enabled);
        }

        public SetChannelEnabled(IPEndPoint IpAddress, Int32 Channel, Boolean Enabled)
            : base(IpAddress)
        {
            SetCommand(Channel, Enabled);
        }

        private void SetCommand(Int32 Channel, Boolean Enabled)
        {
            string _command;
            if (!Enabled)
            {
                _command = string.Format("{0} {1}",_EnableChannelCommand, Channel);
            }
            else
            {
                _command = string.Format("{0} {1}", _DisableChannelCommand, Channel);
            }
            base.CommandToSend = _command;
        }
    } // SetChannelEnabled

    public class GetTime : DewkCommand // GetTime
    {
        public GetTime(string IpAddress)
            : base(new IPEndPoint(IPAddress.Parse(IpAddress), _Port))
        {
            SetCommand();
        }

        public GetTime(IPEndPoint IpAddress)
            : base(IpAddress)
        {
            SetCommand();
        }
        private void SetCommand()
        {
            string command = "SYST:TIME?";
            base.CommandToSend = command;
        }
    }

    public class SetTime : DewkCommand // SetTime
    {
        public SetTime(string IpAddress)
            : base(new IPEndPoint(IPAddress.Parse(IpAddress), _Port))
        {
            SetCommand();
        }

        public SetTime(IPEndPoint IpAddress)
            : base(IpAddress)
        {
            SetCommand();
        }
        private void SetCommand()
        {
            DateTime now = DateTime.Now;
            string command = string.Format("SYST:TIME {0},{1},{2}",now.Hour,now.Minute,now.Second);
            base.CommandToSend = command; 
        }
    }

    public class GetDate : DewkCommand // GetDate
    {
        public GetDate(string IpAddress)
            : base(new IPEndPoint(IPAddress.Parse(IpAddress), _Port))
        {
            SetCommand();
        }

        public GetDate(IPEndPoint IpAddress)
            : base(IpAddress)
        {
            SetCommand();
        }
        private void SetCommand()
        {
            string command = "SYST:DATE?";
            base.CommandToSend = command;
        }
    }

    public class SetDate : DewkCommand // SetDate
    {
        public SetDate(string IpAddress)
            : base(new IPEndPoint(IPAddress.Parse(IpAddress), _Port))
        {
            SetCommand();
        }

        public SetDate(IPEndPoint IpAddress)
            : base(IpAddress)
        {
            SetCommand();
        }
        private void SetCommand()
        {
            DateTime now = DateTime.Now;
            string command = string.Format("SYST:DATE {0},{1},{2}",now.Year,now.Month,now.Day);
            base.CommandToSend = command;
        }
    }

    
    public class GetDisplayUnit : DewkCommand
    {
        public GetDisplayUnit(string IpAddress)
            : base(new IPEndPoint(IPAddress.Parse(IpAddress), _Port))
        {
            SetCommand();
        }
        public GetDisplayUnit(IPEndPoint IpAddress)
            : base(IpAddress)
        {
            SetCommand();
        }
        private void SetCommand()
        {
            string command = string.Format("UNIT:TEMP?");
            base.CommandToSend = command;
        }
    } //GetDisplayUnit

    public class SetDisplayUnit : DewkCommand
    {
        string _DisplayUnit; // should be C or F
        public SetDisplayUnit(string IpAddress, string Unit)
            : base(new IPEndPoint(IPAddress.Parse(IpAddress), _Port))
        {
            _DisplayUnit = Unit;
            SetCommand();
        }
        public SetDisplayUnit(IPEndPoint IpAddress, string Unit)
            : base(IpAddress)
        {
            _DisplayUnit = Unit;
            SetCommand();
        }
        private void SetCommand()
        {
            string command = string.Format("UNIT:TEMP {0}", _DisplayUnit);
            base.CommandToSend = command;
        }
    } //SetDisplayUnit

    public class MakeDewkBeep : DewkCommand
    {
        public MakeDewkBeep(string IpAddress)
            : base(new IPEndPoint(IPAddress.Parse(IpAddress), _Port))
        {
            SetCommand();
        }
        public MakeDewkBeep(IPEndPoint IpAddress)
            : base(IpAddress)
        {
            SetCommand();
        }
        private void SetCommand()
        {
            string command = string.Format("SYST:BEEP");
            base.CommandToSend = command;
        }
    } //MakeDewkBeep

} // NAMESPACE LabMonitorRemote
